package thoven.achievement.net.jsonutil.service

import com.google.gson.GsonBuilder
import io.jsonwebtoken.*
import io.jsonwebtoken.security.Keys
import java.util.*
import javax.crypto.SecretKey

/**
 * JWT 加解密和解析服务
 */
object JwtService {
    
    private val gson = GsonBuilder()
        .setPrettyPrinting()
        .serializeNulls()
        .disableHtmlEscaping()
        .create()
    
    /**
     * 解析 JWT Token（不验证签名）
     */
    fun decode(token: String): Result<String> {
        return try {
            val jwt = token.trim()
            
            // 分割 JWT
            val parts = jwt.split(".")
            if (parts.size != 3) {
                return Result.failure(IllegalArgumentException("Invalid JWT format. Expected 3 parts, got ${parts.size}"))
            }
            
            // 解析 Header
            val header = String(Base64.getUrlDecoder().decode(parts[0]))
            val headerJson = gson.fromJson(header, Map::class.java)
            
            // 解析 Payload
            val payload = String(Base64.getUrlDecoder().decode(parts[1]))
            val payloadJson = gson.fromJson(payload, Map::class.java)
            
            // 格式化输出
            val result = buildString {
                appendLine("=== JWT Header ===")
                appendLine(gson.toJson(headerJson))
                appendLine()
                appendLine("=== JWT Payload ===")
                appendLine(gson.toJson(payloadJson))
                appendLine()
                appendLine("=== JWT Signature ===")
                appendLine(parts[2])
                appendLine()
                
                // 解析常见字段
                appendLine("=== Decoded Claims ===")
                payloadJson.forEach { (key, value) ->
                    when (key) {
                        "exp" -> {
                            val expTime = (value as? Number)?.toLong()?.let {
                                Date(it * 1000)
                            }
                            appendLine("$key (Expiration): $expTime")
                        }
                        "iat" -> {
                            val iatTime = (value as? Number)?.toLong()?.let {
                                Date(it * 1000)
                            }
                            appendLine("$key (Issued At): $iatTime")
                        }
                        "nbf" -> {
                            val nbfTime = (value as? Number)?.toLong()?.let {
                                Date(it * 1000)
                            }
                            appendLine("$key (Not Before): $nbfTime")
                        }
                        else -> appendLine("$key: $value")
                    }
                }
            }
            
            Result.success(result)
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 验证 JWT Token
     */
    fun verify(token: String, secret: String): Result<String> {
        return try {
            val key = Keys.hmacShaKeyFor(secret.toByteArray())
            
            val jws = Jwts.parser()
                .verifyWith(key)
                .build()
                .parseSignedClaims(token)
            
            val result = buildString {
                appendLine("✅ JWT 验证成功！")
                appendLine()
                appendLine("=== Header ===")
                appendLine(gson.toJson(jws.header))
                appendLine()
                appendLine("=== Payload ===")
                appendLine(gson.toJson(jws.payload))
            }
            
            Result.success(result)
        } catch (e: ExpiredJwtException) {
            Result.failure(IllegalArgumentException("JWT 已过期: ${e.message}"))
        } catch (e: SignatureException) {
            Result.failure(IllegalArgumentException("JWT 签名验证失败: ${e.message}"))
        } catch (e: MalformedJwtException) {
            Result.failure(IllegalArgumentException("JWT 格式错误: ${e.message}"))
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 生成 JWT Token
     */
    fun generate(
        payload: Map<String, Any>,
        secret: String,
        expirationMinutes: Int = 60
    ): Result<String> {
        return try {
            val key = Keys.hmacShaKeyFor(secret.toByteArray())
            
            val now = Date()
            val expiration = Date(now.time + expirationMinutes * 60 * 1000)
            
            val builder = Jwts.builder()
                .issuedAt(now)
                .expiration(expiration)
            
            // 添加自定义 claims
            payload.forEach { (key, value) ->
                builder.claim(key, value)
            }
            
            val token = builder.signWith(key).compact()
            
            Result.success(token)
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
    
    /**
     * 从 JSON 生成 JWT
     */
    fun generateFromJson(json: String, secret: String, expirationMinutes: Int = 60): Result<String> {
        return try {
            @Suppress("UNCHECKED_CAST")
            val payload = gson.fromJson(json, Map::class.java) as Map<String, Any>
            generate(payload, secret, expirationMinutes)
        } catch (e: Exception) {
            Result.failure(e)
        }
    }
}

